{-
------------------------------- currying
比如二元函数(+)在接收了参数1后会返回一个新的函数(+1)
而函数(+1)在接收了参数2后会返回一个值3
1 + 2
(+1) 2
3

函数f接收x返回f(x) -- a -> b

Maybe,[],IO 等Type constructors类型构造器，它们都接收一个类型，返回一个新的具体类型
比如Just 1就是一个Maybe Int类型的值
Just操作也可以看成接收一个值，然后把这个值放在一个盒子里
Nothing相当于一个什么都没有的空盒子
Just 1就可以写成f a
------------------------------- Functor
但现在如果我们有一个函数(比如(+3))和一个盒子(比如 Just 1)
该怎么将函数应用在这个盒子的值上呢
函数的输入是一个值，并不能接收一个盒子

这时就要使用fmap函数
fmap接收一个函数和一个装在盒子里的值
它将函数应用在盒子的值上 并返回包含结果的盒子
fmap :: Functor f => (a -> b) -> f a -> f b

对于这个操作
fmap (+3) (Just 1)
可以看作将盒子中的值1取了出来，然后传入给了函数(+3)，返回了4，又装进了盒子中

如果不小心将一个二元函数作为第一个参数传入给了fmap
fmap (+) (Just 3)
那么得到的结果就会是装在盒子里的函数 
Just (+3)

------------------------------- Applicative
所以现在问题来了，怎么将一个装在盒子里的函数 (+3) 应用在装在和盒子里的值 1 上
(<*>) :: Applicative f => f (a -> b) -> f a ->f b

<*>函数接收一个装有函数的盒子 f (a -> b) 和一个装有值的盒子 (f a)
将函数和值全部取出，应用后再把返回的结果放回盒子中

Just (+3) <*> Just 1
盒子中的 +3 和 1 被取了出来
应用后得到结果4 又装回盒子中
Just 4


------------------------------- Monad
如果现在这个函数接收的是一个普通的值，然后返回一个盒子
怎么将这个函数应用在一个盒子上，并得到一个单独的盒子

(>>=) :: Monad m => m a -> (a -> m b) -> m b

>>=先接收一个装有值的盒子 (f a)，然后是一个特殊的接受值返回盒子的函数 ((a -> f b))
最后返回一个盒子 (f b)

Just 1 >>= \x -> Just (x+3)
先将盒子中的值 1 取出来，然后传入给后面这个函数
直接得到作为结果的盒子
Just 4

------------------------------- getLine
用getLine获取文件名
得到的就是一个包在盒子里的字符串

------------------------------- readFile
输入的是在盒子里的字符串(要提取出来)
输出的是一个装有文件内容字符串的盒子

所以可以直接使用
getLine >>= readFile

------------------------------- putStrLn
也是接收一个盒子中的字符串，返回一个盒子的函数
但是会将字符串输出，然后返回一个装有空元组的盒子

所以可以直接使用
getLine >>= readFile >>= putStrLn
-}
{-
------------------------------- zip
>>> zip [1, 2] ['a', 'b']
[(1,'a'),(2,'b')]
------------------------------- map
>>> map (+1) [1, 2, 3]
[2,3,4]
------------------------------- concatMap
>>> concatMap (take 3) [[1..], [10..], [100..], [1000..]]
[1,2,3,10,11,12,100,101,102,1000,1001,1002]
------------------------------- zipWith
>>> zipWith (+) [1, 2, 3] [4, 5, 6]
[5,7,9]
------------------------------- fmap
Maybe
>>> fmap show Nothing
Nothing
>>> fmap show (Just 3)
Just "3"

Either
>>> fmap show (Left 17)
Left 17
>>> fmap show (Right 17)
Right "17"

>>> fmap (*2) [1,2,3]
[2,4,6]

>>> fmap even (2,2)
(2,True)

It may seem surprising that the function is only applied to the 
last element of the tuple compared to the list example above 
which applies it to every element in the list. To understand, 
remember that tuples are type constructors with multiple type parameters: 
a tuple of 3 elements (a,b,c) can also be written (,,) a b c 
and its Functor instance is defined for Functor ((,,) a b) 
(i.e., only the third parameter is free to be mapped over with fmap).

>>> fmap even ("hello", 1.0, 4)
("hello",1.0,True)

------------------------------- fromIntegral
avgSYS1 ss = fromIntegral (sum gList) / fromIntegral (length gList)
    where
      gList = [sys1 s | s <- ss] 
	  
	  
	  
1010 1011
0001 0010
And
0000 0010

-------------------------------- concat
>>> concat (Just [1, 2, 3])
[1,2,3]
>>> concat (Left 42)
[]
>>> concat [[1, 2, 3], [4, 5], [6], []]
[1,2,3,4,5,6]

-------------------------------- concatMap
>>> concatMap (take 3) [[1..], [10..], [100..], [1000..]]
[1,2,3,10,11,12,100,101,102,1000,1001,1002]
>>> concatMap (take 3) (Just [1..])
[1,2,3]

-------------------------------- nub
The nub function removes duplicate elements from a list.
>>> nub [1,2,3,4,3,2,1,2,4,3,5]
[1,2,3,4,5]
import Data.List ( nub, sort )

-------------------------------- toLower
toLower :: Char -> Char
Convert a letter to the corresponding lower-case letter, 
if any. Any other character is returned unchanged.

-------------------------------- toUpper
Convert a letter to the corresponding upper-case letter, 
if any. Any other character is returned unchanged.

-------------------------------- isAlpha
isAlpha :: Char -> Bool

-------------------------------- all
all :: Foldable t => (a -> Bool) -> t a -> Bool
>>> all (> 3) []
True
>>> all (> 3) [1,2]
False
>>> all (> 3) [1,2,3,4,5]
False

-------------------------------- isSuffixOf
Data.List
isSuffixOf :: Eq a => [a] -> [a] -> Bool

The isSuffixOf function takes two lists and returns True 
iff the first list is a suffix of the second. The second list must be finite.

>>> "ld!" `isSuffixOf` "Hello World!"
True
>>> "World" `isSuffixOf` "Hello World!"
False

-------------------------------- isPrefixOf
isPrefixOf :: Eq a => [a] -> [a] -> Bool

The isPrefixOf function takes two lists and returns True iff the first list is a prefix of the second.

>>> "Hello" `isPrefixOf` "Hello World!"
True
>>> "Hello" `isPrefixOf` "Wello Horld!"
False

-------------------------------- isSpace
isSpace :: Char -> Bool

Returns True for any Unicode space character, and 
the control characters \t, \n, \r, \f, \v.

-------------------------------- null
>>> null []
True
>>> null [1]
False

-------------------------------- succ
succ :: a -> a

the successor of a value. For numeric types, succ adds 1.
succ is defined to increment its argument

-------------------------------- even
even :: Integral a => a -> Bool

-------------------------------- <$>
(<$>) :: Functor f => (a -> b) -> f a -> f b 
 ($)  ::              (a -> b) ->   a ->   b

	
>>> show <$> Nothing
Nothing
>>> show <$> Just 3
Just "3"
-}

